home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / math / random-c / random.c < prev   
C/C++ Source or Header  |  1990-05-28  |  5KB  |  163 lines

  1. /*
  2. C This random number generator originally appeared in "Toward a Universal 
  3. C Random Number Generator" by George Marsaglia and Arif Zaman. 
  4. C Florida State University Report: FSU-SCRI-87-50 (1987)
  5. C It was later modified by F. James and published in "A Review of Pseudo-
  6. C random Number Generators" 
  7. C THIS IS THE BEST KNOWN RANDOM NUMBER GENERATOR AVAILABLE.
  8. C       (However, a newly discovered technique can yield 
  9. C         a period of 10^600. But that is still in the development stage.)
  10. C
  11. C It passes ALL of the tests for random number generators and has a period 
  12. C   of 2^144, is completely portable (gives bit identical results on all 
  13. C   machines with at least 24-bit mantissas in the floating point 
  14. C   representation). 
  15. C The algorithm is a combination of a Fibonacci sequence (with lags of 97
  16. C   and 33, and operation "subtraction plus one, modulo one") and an 
  17. C   "arithmetic sequence" (using subtraction).
  18. C======================================================================== 
  19. This C language version was written by Jim Butler, and was based on a
  20. FORTRAN program posted by David LaSalle of Florida State University.
  21. */
  22.  
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25.  
  26. #define TRUE -1
  27. #define FALSE 0
  28. #define boolean int
  29.  
  30. static void rmarin(int ij, int kl);
  31. void ranmar(float rvec[], int len);
  32.  
  33. void main()
  34. {
  35.     float temp[101];
  36.     int ij, kl, len, i;
  37.  
  38.     /* random seeds for the test case: */
  39.     ij = 1802;
  40.     kl = 9373;
  41.  
  42.     /* do the initialization */
  43.     rmarin(ij,kl);
  44.     
  45.     /* generate 20,000 random numbers */
  46.     len = 100;
  47.     for (i=1; i<=200; i++)
  48.         ranmar(temp, len);
  49.         
  50. /*
  51. C If the random number generator is working properly, the next six random
  52. C numbers should be:
  53. C           6533892.0  14220222.0  7275067.0
  54. C           6172232.0  8354498.0   10633180.0
  55. */
  56.      len = 6;
  57.      ranmar(temp,len);
  58.      
  59.      for (i=1; i<=6; i++)
  60.          printf("%12.1f ", 4096.0*4096.0*temp[i]);
  61. }
  62.  
  63. static float u[98], c, cd, cm;
  64. static int i97, j97;
  65. static boolean test = FALSE;
  66.  
  67. static void rmarin(ij,kl)
  68. int ij, kl;
  69. {
  70. /*
  71. C This is the initialization routine for the random number generator RANMAR()
  72. C NOTE: The seed variables can have values between:    0 <= IJ <= 31328
  73. C                                                      0 <= KL <= 30081
  74. C The random number sequences created by these two seeds are of sufficient 
  75. C length to complete an entire calculation with. For example, if sveral 
  76. C different groups are working on different parts of the same calculation,
  77. C each group could be assigned its own IJ seed. This would leave each group
  78. C with 30000 choices for the second seed. That is to say, this random 
  79. C number generator can create 900 million different subsequences -- with 
  80. C each subsequence having a length of approximately 10^30.
  81. C Use IJ = 1802 & KL = 9373 to test the random number generator. The
  82. C subroutine RANMAR should be used to generate 20000 random numbers.
  83. C Then display the next six random numbers generated multiplied by 4096*4096
  84. C If the random number generator is working properly, the random numbers
  85. C should be:
  86. C           6533892.0  14220222.0  7275067.0
  87. C           6172232.0  8354498.0   10633180.0
  88. */
  89.     int i, j, k, l, ii, jj, m;
  90.     float s, t;
  91.     
  92.     if (ij<0 || ij>31328 || kl<0 || kl>30081) {
  93.         puts("The first random number seed must have a value between 0 and 31328.");
  94.         puts("The second seed must have a value between 0 and 30081.");
  95.         exit(1);
  96.     }
  97.     
  98.     i = (ij/177)%177 + 2;
  99.     j = ij%177 + 2;
  100.     k = (kl/169)%178 + 1;
  101.     l = kl%169;
  102.     
  103.     for (ii=1; ii<=97; ii++) {
  104.         s = 0.0;
  105.         t = 0.5;
  106.         for (jj=1; jj<=24; jj++) {
  107.             m = (((i*j)%179)*k) % 179;
  108.             i = j;
  109.             j = k;
  110.             k = m;
  111.             l = (53*l + 1) % 169;
  112.             if ((l*m)%64 >= 32) s += t;
  113.             t *= 0.5;
  114.         }
  115.         u[ii] = s;
  116.     }
  117.     
  118.     c = 362436.0 / 16777216.0;
  119.     cd = 7654321.0 / 16777216.0;
  120.     cm = 16777213.0 / 16777216.0;
  121.     
  122.     i97 = 97;
  123.     j97 = 33;
  124.     
  125.     test = TRUE;
  126. }
  127.  
  128. void ranmar(rvec, len)
  129. float rvec[];    /* len random numbers are placed in rvec[1..len] */
  130. int len;
  131. /*
  132. C This is the random number generator proposed by George Marsaglia in 
  133. C Florida State University Report: FSU-SCRI-87-50
  134. C It was slightly modified by F. James to produce an array of pseudorandom
  135. C numbers.
  136. */
  137. {
  138.     int ivec;
  139.     float uni;
  140.     
  141.     if (test==FALSE) {
  142.         puts("Call the init routine rmarin() before calling ranmar().");
  143.         exit(2);
  144.     }
  145.     for (ivec=1; ivec<=len; ivec++) {
  146.         uni = u[i97] - u[j97];
  147.         if (uni < 0.0) uni += 1.0;
  148.         u[i97] = uni;
  149.         i97--;
  150.         if (i97==0) i97 = 97;
  151.         j97--;
  152.         if (j97==0) j97 = 97;
  153.         c -= cd;
  154.         if (c<0.0) c += cm;
  155.         uni -= c;
  156.         if (uni<0.0) uni += 1.0;
  157.         rvec[ivec] = uni;
  158.     }
  159. }